package com.fivefu.core.camera.services.impl;

import com.fivefu.core.camera.entity.DbMonitorCamera;
import com.fivefu.core.camera.entity.DbMonitorRegion;
import com.fivefu.core.camera.entity.DbMonitorRegionCamera;
import com.fivefu.core.camera.services.*;
import com.fivefu.core.data.vo.TreeVo;
import com.fivefu.core.skyeye.event.entity.DbAiScene;
import com.fivefu.core.skyeye.event.services.DbAiSceneCameraService;
import com.fivefu.core.skyeye.event.services.DbAiSceneService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class CameraTreeServiceImpl implements CameraTreeService {

    @Autowired
    private DbMonitorRegionService dbMonitorRegionService;
    @Autowired
    private DbMonitorRegionCameraService dbMonitorRegionCameraService;
    @Autowired
    private DbMonitorCameraService dbMonitorCameraService;
    @Autowired
    private DbMonitorCameraLabelService dbMonitorCameraLabelService;
    @Autowired
    private DbAiSceneService dbAiSceneService;
    @Autowired
    private DbAiSceneCameraService dbAiSceneCameraService;


    /**
     * 查询树形结构列表
     * @param saveSet 保留探头编号集合
     * @param excludeSet 排除探头编号集合
     * @return
     */
    public List<TreeVo> getMonitorRegionTreeStructure(Set<String> saveSet , Set<String> excludeSet) {
        List<TreeVo> resultList = new ArrayList<>();
        //查询自定义探头组织表所有数据信息
        List<DbMonitorRegion> monitorRegions = dbMonitorRegionService.queryMonitorRegionAllList();

        //获取组织探头关联表所有数据集
        List<DbMonitorRegionCamera> regionCameras = dbMonitorRegionCameraService.queryRegionCameras();
        //将查询结果根据组织id分组
        Map<Long,List<DbMonitorRegionCamera>> regionCameraMap = regionCameras.stream().collect(Collectors.groupingBy(k -> k.getRegionId(),Collectors.toList()));

        //查询所有探头数据
        List<DbMonitorCamera> cameraList = dbMonitorCameraService.queryMonitorCameraList();
        //将查询结果根据探头编号分组
        Map<String,DbMonitorCamera> cameraMap = cameraList.stream().filter(k -> {
            if (excludeSet != null){
                if (excludeSet.contains(k.getCameraCode())){
                    return false;
                }
            }
            if (saveSet != null){
                if (!saveSet.contains(k.getCameraCode())){
                    return false;
                }
            }
            return true;
        }).collect(Collectors.toMap(k -> k.getCameraCode().toString(),v -> v));


        //将所有自定义探头组织数据及关联的探头信息转存到resultList中
        resultList = converTreeList(monitorRegions,regionCameraMap,cameraMap);
        return resultList;
    }

    /**
     * 获取树形结构
     * @param monitorRegions         自定义探头组织信息
     * @param regionCameraMap        组织探头关联信息
     * @param cameraMap              探头信息
     * @return
     */
    private List<TreeVo> converTreeList(List<DbMonitorRegion> monitorRegions, Map<Long, List<DbMonitorRegionCamera>> regionCameraMap, Map<String, DbMonitorCamera> cameraMap) {
        List<TreeVo> resultList = new ArrayList<>();
        //遍历自定义探头组织信息开始转换
        for (DbMonitorRegion monitorRegion : monitorRegions) {
            TreeVo treeVo = new TreeVo();
            treeVo.setId("region_" + monitorRegion.getId().toString());
            treeVo.setNodeId(monitorRegion.getId().toString());
            treeVo.setName(monitorRegion.getRegionName());
            treeVo.setType("region");
            if (monitorRegion.getParentRegionId().equals(0L)) {
                treeVo.setPid("0");
            }else{
                treeVo.setPid("region_" + monitorRegion.getParentRegionId());
            }
            treeVo.setParentId(monitorRegion.getParentRegionId().toString());
            resultList.add(treeVo);

            //判断组织探头关联集合是否包含该探头组织
            if(regionCameraMap.containsKey(monitorRegion.getId())) {
                List<DbMonitorRegionCamera> regionCameraList = regionCameraMap.get(monitorRegion.getId());
                for (DbMonitorRegionCamera dbMonitorRegionCamera : regionCameraList) {
                    String code = dbMonitorRegionCamera.getCameraCode();
                    if (cameraMap.containsKey(code)) {
                        DbMonitorCamera monitorCamera = cameraMap.get(code);
                        if (monitorCamera != null) {
                            TreeVo vo = new TreeVo();
                            vo.setId("camera_"+monitorCamera.getId().toString());
                            vo.setNodeId(monitorCamera.getId().toString());
                            vo.setCode(code);
                            vo.setName(monitorCamera.getCameraName());
                            vo.setType("camera");
                            vo.setPid("region_" + monitorRegion.getId().toString());
                            vo.setParentId(monitorRegion.getId().toString());
                            resultList.add(vo);
                        }
                    }
                }
            }
        }
        return resultList;
    }

    /**
     * 查询树形结构子父级关系
     * @param saveSet 保留探头编号集合
     * @param excludeSet 排除探头编号集合
     * @return
     */
    public List<TreeVo> getMonitorRegionTreeChildrenList(Set<String> saveSet , Set<String> excludeSet) {
        List<TreeVo> treeVoList = getMonitorRegionTreeStructure( saveSet , excludeSet);
        List<TreeVo> resultList = queryTreeListByParentId("0", treeVoList);
        return resultList;
    }

    /**
     *递归查询下级结构
     * @param parentId     父级组织id
     * @param treeList     树形结构信息
     * @return
     */
    private List<TreeVo> queryTreeListByParentId(String parentId, List<TreeVo> treeList) {
        List<TreeVo> resultList = treeList.stream().filter(k -> k.getPid().equals(parentId)).collect(Collectors.toList());
        for (TreeVo treeVo : resultList) {
            List<TreeVo> childers = queryTreeListByParentId(treeVo.getId(), treeList);
            treeVo.setChildren(childers);
        }
        return resultList;
    }

    /**
     * 查询探头树形结构
     * @param type 查询类型(list,tree)
     * @return
     */
    @Override
    public List<TreeVo> getMonitorRegionTree(String type){
        return getMonitorRegionTree(type,null,null);
    }

    /**
     * 查询探头树形结构
     * @param type 查询类型(list,tree)
     * @param saveSet 保留探头编号集合
     * @param excludeSet 排除探头编号集合
     * @return
     */
    public List<TreeVo> getMonitorRegionTree(String type, Set<String> saveSet , Set<String> excludeSet){
        List<TreeVo> list;
        if (type.equals("tree")){
            list = getMonitorRegionTreeChildrenList(saveSet, excludeSet);
        }else{
            list = getMonitorRegionTreeStructure(saveSet, excludeSet);
        }
        return list;
    }

    /**
     * 查询 新增标签下探头 树形结构
     * @param type 查询类型(list,tree)
     * @param labelId 标签编号
     * @return
     */
    @Override
    public List<TreeVo> getAddMonitorRegionTreeByLabelId(String type, Long labelId){
        List<Long> labels = new ArrayList<>();
        labels.add(labelId);
        Set<String> codeSet = dbMonitorCameraLabelService.queryMonitorCameraByLabelIds(labels);
        if (codeSet != null && codeSet.size() == 0){
            codeSet = null;
        }
        List<TreeVo> list = getMonitorRegionTree(type, null, codeSet);
        return list;
    }

    /**
     * 查询 新增场景下探头 树形结构
     * @param type 查询类型(list,tree)
     * @param sceneId 场景编号
     * @return
     */
    @Override
    public List<TreeVo> getAddMonitorRegionTreeBySceneId(String type, Long sceneId){
        DbAiScene scene = dbAiSceneService.querySceneByID(sceneId);
        Set<String> codeSet = null;
        if (scene != null){
            List<String> codeList = dbAiSceneCameraService.queryCameraCodeBySceneID(scene.getCode(), null);
            if (codeList != null && !codeList.isEmpty()){
                codeSet = codeList.stream().collect(Collectors.toSet());
            }
        }
        List<TreeVo> list = getMonitorRegionTree(type, null, codeSet);
        return list;
    }

}
